﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Quexcel.OpenXML.Interfaces;
using System.Xml;
using System.IO.Packaging;
using System.IO;
using Quexcel.OpenXML.Excel.SharedString;
using Quexcel.OpenXML.Utils;
using System.Text.RegularExpressions;
using Quexcel.OpenXML.Excel.Worksheet.Components;

namespace Quexcel.OpenXML.Excel.Worksheet.IO
{
    internal class WorksheetReader : IWorksheetReader
    {
        protected XmlDocument worksheetDoc;
        protected PackagePart sheetPart;
        protected SharedStringData sharedStringData;
        protected XmlNamespaceManager nsManager;
        protected bool isDisposed = false;

        internal WorksheetReader(PackagePart sheetPart, SharedStringData sharedStringData, XmlNamespaceManager nsManager)
        {
            this.sharedStringData = sharedStringData;
            worksheetDoc = new XmlDocument();
            worksheetDoc.Load(sheetPart.GetStream());
            this.sheetPart = sheetPart;
            this.nsManager = nsManager;
        }

        #region IReader Members

        public Row ReadRow(int index)
        {
            Row dataRow = new Row(index, sheetPart);
            XmlNode rowNode = worksheetDoc.SelectSingleNode(string.Format(
                                        "//d:sheetData/d:row[@r='{0}']", index.ToString()), nsManager);
            if (rowNode != null)
            {
                XmlNodeList cellNodes = rowNode.SelectNodes("./d:c", nsManager);
                if (cellNodes != null)
                {
                    foreach (XmlNode node in cellNodes)
                    {
                        int styleIndex = -1;
                        if (node.Attributes["s"] != null)
                            styleIndex = Int32.Parse(node.Attributes["s"].Value);

                        Cell cell = (Cell)dataRow.NewCell(new Address(node.Attributes["r"].Value), styleIndex);
                        if (node.Attributes["t"] != null && node.Attributes["t"].Value == "s")
                        {
                            int sharedStringIndex = Int32.Parse(node.SelectSingleNode("./d:v", nsManager).InnerText);
                            cell.Value = sharedStringData.GetReader().ReadSharedString(sharedStringIndex);
                        }
                        else
                            cell.Value = node.SelectSingleNode("./d:v", nsManager).InnerText;

                        dataRow.Cells.Add(cell);
                    }
                }
            }

            return dataRow;
        }

        public string Read(string addressName)
        {
            Address address = Util.GetAddress(addressName);
            XmlNode rowNode = worksheetDoc.SelectSingleNode(string.Format(
                                        "//d:sheetData/d:row[@r='{0}']", address.row.ToString()), nsManager);

            return Read(rowNode, address);
        }
        private string Read(XmlNode rowNode, Address address)
        {
            if (rowNode != null)
            {
                XmlNode cellNode = rowNode.SelectSingleNode(String.Format("./d:c[@r='{0}']", address.ToString()), nsManager);
                if (cellNode != null)
                {
                    if (cellNode.Attributes["t"] != null && cellNode.Attributes["t"].Value == "s")
                    {
                        int sharedStringIndex = Int32.Parse(cellNode.SelectSingleNode("./d:v", nsManager).InnerText);
                        return sharedStringData.GetReader().ReadSharedString(sharedStringIndex);
                    }
                    else
                    {
                        return cellNode.SelectSingleNode("./d:v", nsManager).InnerText;
                    }
                }
            }

            return null;
        }

        public void Close()
        {
            
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            worksheetDoc = null;
            this.Close();
            isDisposed = true;
        }

        public bool IsDisposed
        {
            get { return isDisposed; }
        }

        #endregion
    }
}
